import java.io.*;
import java.net.*;
import java.nio.file.*;
import java.text.*;
import java.util.*;

public class Cache {
    private static final String PATH = "cache.txt";
    private final Path cacheFilePath = Paths.get(PATH);
    private final Map<String, String[]> cache = new HashMap<>();
    private final Object cacheLock = new Object();

    public Cache() {
        if (!Files.exists(cacheFilePath)) {
            try {
                Files.createFile(cacheFilePath);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    public InetAddress getIpFromCache(String domain) {
        Random rand = new Random();
        synchronized (cacheLock) {
            if (cache.containsKey(domain)) {
                try {
                    return InetAddress.getByName(cache.get(domain)[rand.nextInt(cache.get(domain).length)]);
                } catch (UnknownHostException e) {
                    throw new RuntimeException(e);
                }
            }
        }
        return null;
    }

    public void readCacheFromFile() {
        synchronized (cacheLock) {
            try (BufferedReader br = Files.newBufferedReader(cacheFilePath)) {
                String line;
                while ((line = br.readLine()) != null) {
                    String[] contents = line.split(" ");
                    String[] ips = Arrays.copyOfRange(contents, 2, contents.length);
                    cache.put(contents[1], ips);
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    public void addCacheToFile(String domain, ArrayList<InetAddress> ips) {
        synchronized (cacheLock) {
            try (BufferedWriter bw = Files.newBufferedWriter(cacheFilePath, StandardOpenOption.APPEND)) {
                SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");
                String line = formatter.format(new Date()) + " " + domain;
                for (InetAddress ip : ips) {
                    line += (" " + ip.toString().substring(1));
                }
                bw.write(line);
                bw.newLine();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            readCacheFromFile();
        }
    }

    public void flushCacheFile(int limit) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.HOUR_OF_DAY, -limit * 24);
        Date expireDate = calendar.getTime();
        StringBuilder newCache = new StringBuilder();
        synchronized (cacheLock) {
            try (BufferedReader br = Files.newBufferedReader(cacheFilePath)) {
                String line;
                while ((line = br.readLine()) != null) {
                    String[] contents = line.split(" ");
                    if (contents[0].equals("blacklist")) {
                        newCache.append(line).append("\n");
                    } else {
                        Date cacheDate = dateFormat.parse(contents[0]);
                        if (cacheDate.after(expireDate)) {
                            newCache.append(line).append("\n");
                        }
                    }
                }
            } catch (IOException | ParseException e) {
                throw new RuntimeException(e);
            }
            try (BufferedWriter bw = Files.newBufferedWriter(cacheFilePath, StandardOpenOption.TRUNCATE_EXISTING)) {
                bw.write(newCache.toString());
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            readCacheFromFile();
        }
    }

    public Object getCacheLock() {
        return cacheLock;
    }
}